package org.course.weather.task;

import com.alibaba.fastjson2.JSON;
import org.course.weather.config.BaiduAPIConfig;
import org.course.weather.service.WeatherService;
import org.course.weather.entity.WeatherBean;
import org.course.weather.util.MyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson2.JSONObject;

@EnableScheduling
@Component
public class ScheduleTask {
    @Autowired BaiduAPIConfig baiduAPIConfig;
    @Autowired WeatherService weatherService;

    // 全局HttpClient:
    private static final HttpClient httpClient = HttpClient.newBuilder().build();

    // 全国主要城市区域编码
    private static final Map<Integer, String> districtMap = new HashMap<>();
    static {
        districtMap.put(110100, "北京市");
        districtMap.put(510100, "成都市");
        districtMap.put(310100, "上海市");
        districtMap.put(500100, "重庆市");
        districtMap.put(511400, "眉山市");
        districtMap.put(511600, "广安市");
    }

    @Scheduled(fixedDelay = 1000 * 60 * 10) // 每10分钟执行一次
    void callWeatherAPI() throws Exception {
        System.out.printf("Ready to call weather API at %s%n", MyUtil.DTStr(LocalDateTime.now()));

        String url = baiduAPIConfig.getUrl(); // 从配置类中，得到百度地图的天气API接口url

        // 遍历主要城市区域编码，获取天气实况
        for (Map.Entry<Integer,String> item : districtMap.entrySet()) {
            Integer district_id = item.getKey(); // 城市区域编码

            String resp = httpGet(url + district_id);

            // 返回的是一个字符串 json格式。用fastjson转换为java的Map对象
            // 需要对照百度天气的接口文档里描述的返回结果json结构来写代码
            JSONObject jsonObject = JSON.parseObject(resp);

            //根据返回json数据格式，先判断是否返回了错误信息
            int resp_status = jsonObject.getIntValue("status");
            if ( resp_status != 0 ) {
                throw new RuntimeException(jsonObject.getString("message"));
            }

            //没有出错，将json格式中的result转换为我们自己的javabean
            BaiduAPIResp baidu_resp = jsonObject.getJSONObject("result").toJavaObject(BaiduAPIResp.class);
            System.out.println(jsonObject);

            //将数据存入数据库
            weatherService.UpdateCityWeather(new WeatherBean(
                    district_id,
                    baidu_resp.getLocation().getCity(), //城市
                    baidu_resp.getNow().getText(), //天气现象
                    baidu_resp.getNow().getWind_dir(), //风向
                    baidu_resp.getNow().getWind_class(), //风力
                    baidu_resp.getNow().getTemp(), //气温
                    baidu_resp.getNow().getUptime() //更新时间
            ));

            // 休眠1秒，百度有每秒3次的并发请求限制
            Thread.sleep(1000);
        }

        System.out.printf("Finish to call weather API at %s%n", MyUtil.DTStr(LocalDateTime.now()));
    }

    static String httpGet(String url) throws Exception {
        HttpRequest request = HttpRequest.newBuilder(new URI(url))
                // 设置Header:
                .header("User-Agent", "Java HttpClient").header("Accept", "*/*")
                // 设置超时:
                .timeout(Duration.ofSeconds(5))
                // 设置版本:
                .version(HttpClient.Version.HTTP_2).build();
        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        return response.body();
    }
}
